package main

import (
	"fmt"
	"sync"
	"time"
)

type jobManager struct {
	jobMutex sync.RWMutex
	// 增量更新
	activeJobs map[string]deployJob
}

func NewJobManager() *jobManager {
	return &jobManager{
		jobMutex:   sync.RWMutex{},
		activeJobs: make(map[string]deployJob),
	}
}

func (jm *jobManager) sync(jobs []deployJob) {
	// 增量更新
	m := make(map[string]deployJob)

	for _, v := range jobs {
		m[v.GetName()] = v
	}
	jm.jobMutex.Lock()
	defer jm.jobMutex.Unlock()
	for k, jmv := range jm.activeJobs {
		if mv, isok := m[k]; isok && jmv.GetKind() == mv.GetKind() {
			delete(m, k)
		} else {
			go jm.activeJobs[k].Stop()
			delete(jm.activeJobs, k)
		}
	}
	for k, v := range m {
		jm.activeJobs[k] = v
		go jm.activeJobs[k].Start()
	}
}

type deployJob interface {
	Start()
	Stop()
	GetName() string
	GetFlag() bool
	GetKind() string
	SetFlag(bool)
}

type k8sD struct {
	Name string
	Flag bool
	Kind string
}

func NewK8sD(name string) *k8sD {
	return &k8sD{
		Name: name,
		Kind: "k8sD",
	}
}

func (k *k8sD) Start() {
	k.SetFlag(true)
	fmt.Printf("Host %2s 开始运行 \n", k.Name)
	c := 0
	for {
		if k.Flag {
			fmt.Printf("K8S %3s 正在运行第%d次 \n", k.Name, c)
			c++
			time.Sleep(5 * time.Second)
		} else {
			fmt.Printf("K8s %3s 退出 \n", k.Name)
			break
		}
	}
}

func (k *k8sD) Stop() {
	k.SetFlag(false)
	fmt.Printf("k8s %3s 准备退出 \n", k.Name)
}

func (k *k8sD) GetFlag() bool {
	return k.Flag
}

func (k *k8sD) SetFlag(B bool) {
	k.Flag = B
}

func (k *k8sD) GetName() string {
	return k.Name
}

func (k *k8sD) GetKind() string {
	return k.Kind
}

type host struct {
	Name string
	Flag bool
	Kind string
}

func NewHost(name string) *host {
	return &host{
		Name: name,
		Kind: "Host",
	}
}

func (h *host) GetKind() string {
	return h.Kind
}

func (h *host) Start() {
	h.SetFlag(true)
	fmt.Printf("Host %2s 开始运行 \n", h.Name)
	c := 0
	for {
		if h.Flag {
			fmt.Printf("Host %2s 正在运行第%d次 \n", h.Name, c)
			c++
			time.Sleep(5 * time.Second)
		} else {
			fmt.Printf("Host %2s 退出\n", h.Name)
			break
		}
	}
}

func (h *host) Stop() {
	h.Flag = false
	fmt.Printf("Host %2s 准备退出 \n", h.Name)
}

func (h *host) GetFlag() bool {
	return h.Flag
}

func (h *host) SetFlag(B bool) {
	h.Flag = B
}

func (h *host) GetName() string {
	return h.Name
}

func main() {
	jm := NewJobManager()
	go jm.sync([]deployJob{NewK8sD("a"), NewHost("b"), NewHost("c")})
	time.Sleep(10 * time.Second)
	go jm.sync([]deployJob{NewHost("a"), NewHost("b"), NewK8sD("c")})
	time.Sleep(10 * time.Second)
	go jm.sync([]deployJob{NewK8sD("e"), NewHost("b"), NewHost("c")})
	time.Sleep(10 * time.Second)
	go jm.sync([]deployJob{NewK8sD("d"), NewHost("b"), NewHost("c")})
	time.Sleep(10 * time.Second)
	go jm.sync([]deployJob{NewK8sD("d"), NewHost("b"), NewHost("c")})
	time.Sleep(10 * time.Second)
}
// 